package scottb.flex.navigate;

import javax.xml.crypto.Data;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class Navigator {

    private int selectedIndex;
    private INavItem selectedItem;
    private Container container;

    private List<INavItem> items = new ArrayList<INavItem>();
    private List<NavigatorListener> listeners = new ArrayList<NavigatorListener>();

    public Navigator() {
    }

    public Navigator(Container container) {
        this.container = container;
    }

    public void add(INavItem item) {
        items.add(item);
    }

    public void remove(INavItem item) {
        items.remove(item);
    }

    public INavItem[] array() {
        return items.toArray(new INavItem[0]);
    }

    public void addListener(NavigatorListener listener) {
        listeners.add(listener);
    }

    public void removeListener(NavigatorListener listener) {
        listeners.remove(listener);
    }

    public Container getContainer() {
        return container;
    }

    public void setContainer(Container container) {
        this.container = container;
    }

    public void navigate(String id) {
        navigate(id, null, false);
    }

    public void navigate(String id, Object data) {
        navigate(id, data, false);
    }

    public void navigate(String id, boolean back) {
        navigate(id, null, back);
    }

    public void navigate(String id, Object data, boolean back) {

        for(INavItem item : items) {
            if(item.getId().equals(id)) {
                navigate(item, data, false);
                return;
            }
        }

        throw new IllegalArgumentException(id);
    }

    public void navigate(int index) {
        navigate(index, null, false);
    }

    public void navigate(int index, Object data) {
        navigate(index, data, false);
    }

    public void navigate(int index, boolean back) {
        navigate(index, null, back);
    }

    public void navigate(int index, Object data, boolean back) {

        INavItem destination = items.get(index);

        navigate(destination, data, back);
    }

    public void navigate(INavItem destination) {
        navigate(destination, null, false);
    }

    public void navigate(INavItem destination, Object data) {
        navigate(destination, data, false);
    }

    public void navigate(INavItem destination, boolean back) {
        navigate(destination, null, back);
    }

    public void navigate(INavItem destination, Object data, boolean back) {

        if(exit(destination, data, back)) {
            enter(destination, data, back);
        }
    }

    private boolean exit(INavItem destination, Object data, boolean back) {

        if(null != selectedItem) {

            if(null != selectedItem.getExitHandler()) {

                return selectedItem.getExitHandler().exit(destination, data, back);
            }

            container.remove(selectedItem.getView());
        }

        return true;
    }

    private void enter(INavItem destination, Object data, boolean back) {

        if(null != destination.getEnterHandler()) {

            destination.getEnterHandler().enter(data, back, selectedItem);
        }

        container.add(destination.getView());
        container.validate();
        container.repaint();

        NavEvent event = new NavEvent(this, selectedItem, destination);

        selectedItem = destination;
        selectedIndex = items.indexOf(destination);

        for(NavigatorListener listener : listeners) {
            listener.navChanged(event);
        }
    }
}
